package com.inspur.edp.common.expr.visitor.array;

import com.inspur.edp.common.expr.ast.ASTContext;
import com.inspur.edp.common.expr.ast.CompileUnitParser;
import com.inspur.edp.common.expr.ast.CompileUnitVisitor;
import com.inspur.edp.common.expr.constant.ExpressConstant;
import com.inspur.edp.common.expr.exception.ExpressException;
import com.inspur.edp.common.expr.parser.ExpressAstParser;
import com.inspur.edp.common.expr.spi.ArrayAccessVisitor;
import com.inspur.edp.common.expr.visitor.VisitResult;
import com.inspur.edp.common.type.TypeRefer;


/**
 * @author lizhaorui
 * @description TODO
 * @date 2025/1/20 14:59
 */
public class JsonArrayAccessVisitor implements ArrayAccessVisitor {

    @Override
    public String getKind() {
        return ExpressConstant.JSON_ARRAY_ACCESS_KIND;
    }

    @Override
    public VisitResult visitGetter(CompileUnitVisitor visitor,
                                   ASTContext context,
                                   CompileUnitParser.ExpressContext objectExpr,
                                   CompileUnitParser.ExpressContext indexExpress) {

        TypeRefer objectType = ExpressAstParser.getOriginalType(objectExpr, context);
        TypeRefer itemType = objectType.getGenericType(0);
        VisitResult result = new VisitResult();
        String script = null;
        String objectExprDsl = visitor.visitExpress(objectExpr).toString();
        String indexExpressDsl = visitor.visitExpress(indexExpress).toString();
        //基本类型、数组类型、对象类型
        if (itemType.isInt()) {
            script = String.format("%s.get(%s).asInt()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isDouble()) {
            script = String.format("%s.get(%s).asDouble()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isFloat()) {
            script = String.format("%s.get(%s).asDouble()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isLong()) {
            script = String.format("%s.get(%s).asLong()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isBigDecimal()) {
            script = String.format("%s.get(%s).asDouble()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isString()) {
            script = String.format("%s.get(%s).asText()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isBoolean()) {
            script = String.format("%s.get(%s).asBoolean()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isDateTime()) {
            script = String.format("%s.get(%s).asText()", objectExprDsl, indexExpressDsl);
        } else if (itemType.isList()) {
            script = String.format("(ArrayNode) %s.get(%s)", objectExprDsl, indexExpressDsl);
            result.addImport("com.fasterxml.jackson.databind.node.ArrayNode");
        } else {
            script = String.format("(ObjectNode) %s.get(%s)", objectExprDsl, indexExpressDsl);
            result.addImport("com.fasterxml.jackson.databind.node.ObjectNode");
        }
        result.setScript(script);
        return result;
    }

    @Override
    public VisitResult visitSetter(CompileUnitVisitor visitor,
                                   ASTContext context,
                                   CompileUnitParser.ExpressContext objectExpr,
                                   CompileUnitParser.ExpressContext indexExpress,
                                   CompileUnitParser.ExpressContext valueExpress) {
        TypeRefer objectType = ExpressAstParser.getOriginalType(objectExpr, context);
        TypeRefer itemType = objectType.getGenericType(0);
        VisitResult result = new VisitResult();
        String script = null;
        String objectExprDsl = visitor.visitExpress(objectExpr).toString();
        String indexExpressDsl = visitor.visitExpress(indexExpress).toString();
        //基本类型、数组类型、对象类型
        if (itemType.isInt() ||
                itemType.isDouble() ||
                itemType.isFloat() ||
                itemType.isLong() ||
                itemType.isBigDecimal() ||
                itemType.isString() ||
                itemType.isBoolean() ||
                itemType.isDateTime()) {
            script = String.format("%s.add(%s)", objectExprDsl, indexExpressDsl);
            result.setScript(script);
            return result;
        } else {
            throw new ExpressException("json array not support set.");
        }
    }
}
